package goDaemo

import (
	"fmt"
	"db2s/global"
	"log"
	"os"
	"os/exec"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
	"time"
)

// 检查pid文件是否存在
func pidCheck(s string) bool {
	var pidFile string
	if len(s) == 0 {
		pidFile = global.PidFile
	} else {
		pidFile = s
	}
	// 检查 PID 文件是否已存在
	if _, err := os.Stat(pidFile); err == nil {
		fmt.Println(fmt.Sprintf("%v report: The current pid file %v exists, please check whether the service has been started!!!", global.ProcessName, pidFile))
		return true
	}
	return false
}
func socketCheck(s string) bool {
	var scoketFile string
	if len(s) == 0 {
		scoketFile = global.SocketFile
	} else {
		scoketFile = s
	}
	// 检查 socket 文件是否已存在
	if _, err := os.Stat(scoketFile); err == nil {
		fmt.Println(fmt.Sprintf("%v report: The current socket file %v exists, please check whether the service has been started!!!", global.ProcessName, scoketFile))
		return true
	}
	return false
}

// 创建pid文件，并写入当前子进程（次父进程）pid
func pidCreate(s string) bool {
	// 创建 PID 文件
	var pidFile string
	if len(s) == 0 {
		pidFile = global.PidFile
	} else {
		pidFile = s
	}
	file, err := os.Create(pidFile)
	if err != nil {
		fmt.Println(fmt.Sprintf("%v report: Failed to create pid file %v, error info is {%v} !!!", global.ProcessName, pidFile, err))
		return false
	}
	// 写入当前进程的 PID
	if _, err = file.WriteString(fmt.Sprintf("%d", os.Getpid())); err != nil {
		fmt.Println(fmt.Sprintf("%v report: Failed to write pid file %v,write string is {%v},error info is {%v} !!!", global.ProcessName, pidFile, os.Getpid(), err))
		return false
	}
	if err = file.Close(); err != nil {
		fmt.Println(fmt.Sprintf("%v report: Failed to close pid file %v,error info is {%v} !!!", global.ProcessName, pidFile, err))
		return false
	}
	return true
}

// 创建socket文件
func socketCreate(s string) bool {
	// 创建 PID 文件
	var socketFile string
	if len(s) == 0 {
		socketFile = global.SocketFile
	} else {
		socketFile = s
	}
	file, err := os.Create(socketFile)
	if err != nil {
		fmt.Println(fmt.Sprintf("%v report: Failed to create pid file %v, error info is {%v} !!!", global.ProcessName, socketFile, err))
		return false
	}
	// 写入当前进程的 PID
	if _, err = file.WriteString(fmt.Sprintf("%d", os.Getpid())); err != nil {
		fmt.Println(fmt.Sprintf("%v report: Failed to write pid file %v,write string is {%v},error info is {%v} !!!", global.ProcessName, socketFile, os.Getpid(), err))
		return false
	}
	if err = file.Close(); err != nil {
		fmt.Println(fmt.Sprintf("%v report: Failed to close pid file %v,error info is {%v} !!!", global.ProcessName, socketFile, err))
		return false
	}
	return true
}

// RepeatProcessCheck 检查pid和socket文件是否存在
func RepeatProcessCheck(s string) bool {
	switch {
	case strings.HasSuffix(strings.ToLower(s), ".pid"):
		return pidCheck(s)
	case strings.HasSuffix(strings.ToLower(s), ".sock"):
		return socketCheck(s)
	default:
		fmt.Println(fmt.Sprintf("%v report: The incoming file is incorrect and the file %v format ends with .pid or .sock.!!!", s))
		return true
	}
}
func FileLock(s string) bool {
	var (
		fileLock string
	)
	if len(s) == 0 {
		fileLock = global.FileLock
	} else {
		fileLock = s
	}
	// 创建锁文件
	file, err := os.OpenFile(fileLock, os.O_CREATE|os.O_RDWR, 0666)
	if err != nil {
		fmt.Println(fmt.Sprintf("%v report: Failed to open file lock %v,error info is {%v} !!!", global.ProcessName, fileLock, err))
		return false
	}
	// 定义锁定结构
	exec.Command()
	return false
}
func FileUnlock() bool {
	// 解锁结构
	unlock := syscall.Flock_t{
		Type:   syscall.F_UNLCK, // 解锁
		Whence: 0,
		Start:  0,
		Len:    0,
	}
	// 尝试解锁
	err := syscall.FcntlFlock(file.Fd(), syscall.F_SETLK, &unlock)
	if err != nil {
		return false
	}
	return true
}

// CreateIdentificationFile 创建 pid 和socket
func CreateIdentificationFile(s string) bool {

}

// RemoveIdentificationFile 在程序退出时删除 pid/socket 文件
func RemoveIdentificationFile() bool {
	for _, v := range []string{
		global.PidFile,
		global.SocketFile,
	} {
		if err := os.Remove(v); err != nil {
			return false
		}
	}
	return true
}
func StartService() {
	if RepeatProcessCheck("") {
		os.Exit(1)
	}

}
func main() {
	fmt.Println("程序开始运行...")
	if len(os.Args) > 1 {
		switch os.Args[1] {
		case "start":
			startDaemon()
			return
		case "stop":
			stopDaemon()
			return
		case "fork":
			forkChildProcess()
			return
		case "list":
			listProcesses()
			return
		}
	}

	log.Println("请使用 'start'、'stop'、'fork' 或 'list' 参数来启动、停止、创建子进程或列出进程。")
}

// startDaemon 启动守护进程
func startDaemon() {
	if _, err := os.Stat(socketFile); !os.IsNotExist(err) {
		log.Println("守护进程已经在运行。")
		return
	}

	// 启动当前程序本身，传递 "run" 参数
	proc, err := os.StartProcess(os.Args[0], []string{os.Args[0], "run"}, &os.ProcAttr{})
	if err != nil {
		log.Fatal("启动守护进程失败:", err)
	}

	// 记录守护进程的 PID
	daemonPID = proc.Pid

	if err := os.WriteFile(socketFile, []byte("running"), 0644); err != nil {
		log.Fatal("创建 socket 文件失败:", err)
	}

	log.Println("守护进程已启动，PID:", daemonPID)
}

// forkChildProcess 创建子进程并授权
func forkChildProcess() {
	pid, err := syscall.ForkExec(os.Args[0], []string{os.Args[0], "run"}, &syscall.ProcAttr{
		Sys: &syscall.SysProcAttr{
			Setpgid: true,
		},
	})
	if err != nil {
		log.Fatal("创建子进程失败:", err)
	}

	log.Println("子进程已创建，PID:", pid)
}

// listProcesses 列出当前的父进程和子进程
func listProcesses() {
	// 使用守护进程的 PID
	fmt.Printf("守护进程ID: %d\n", daemonPID)

	// 列出子进程
	fmt.Println("子进程:")
	cmd := exec.Command("pgrep", "-P", strconv.Itoa(daemonPID))
	output, err := cmd.Output()
	if err != nil {
		log.Fatalf("获取子进程失败: %v", err)
	}

	children := string(output)
	if children == "" {
		fmt.Println("没有找到子进程.")
	} else {
		fmt.Println(children)
	}
}

// run 处理守护进程的逻辑
func run() {
	log.Println("我是守护进程:", os.Getpid())
	go handleSignals()
	monitorStopSignal()
	log.Println("守护进程结束:", os.Getpid())
}

// stopDaemon 用于停止守护进程
func stopDaemon() {
	if err := os.WriteFile(stopFile, []byte("stop"), 0644); err != nil {
		log.Fatalf("创建停止文件失败: %v", err)
	}
	log.Println("守护进程已请求停止")
	os.Remove(socketFile)
}

// handleSignals 处理停止信号
func handleSignals() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGTERM)

	<-c // 等待停止信号
	log.Println("收到停止信号，正在退出...")
	os.Remove(socketFile)
	os.Exit(0)
}

// monitorStopSignal 监控停止信号
func monitorStopSignal() {
	for {
		if _, err := os.Stat(stopFile); os.IsNotExist(err) {
			time.Sleep(1 * time.Second) // 每秒检查一次
			continue
		}
		log.Println("收到停止信号，正在退出...")
		os.Remove(stopFile)
		return
	}
}

// main 函数的入口，处理 "run" 参数
func init() {
	if len(os.Args) > 1 && os.Args[1] == "run" {
		run() // 调用 run 函数
		os.Exit(0)
	}
}
